package com.example.demo.Controller;

import com.example.demo.component.OnlineUserManager;
import com.example.demo.model.*;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.List;


@Component
public class WebSocketController extends TextWebSocketHandler {
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private MessageSessionMapper messageSessionMapper;
    @Autowired
    private MessageMapper messageMapper;
    private ObjectMapper objectMapper = new ObjectMapper();
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception{
        System.out.println("[WebSocketController]连接成功!");
        //先获取对象
        User user=(User) session.getAttributes().get("user");
        if(user == null){
            return;
        }
//        System.out.println("获取当前的userId: "+user.getUserId());
        //把这个键值对存起来
        onlineUserManager.online(user.getUserId(), session);
    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        System.out.println("[WebSocketController]收到消息!"+message.toString());
        //1.先获取当前用户信息，处理消息的接收，转发和保存记录
        User user = (User) session.getAttributes().get("user");
        if(user == null) {
            System.out.println("[WebSocketController] user为空，未登录，无法进行消息转发");
            return;
        }
        //2.针对请求进行解析,把json格式的字符串，转成一个Java对象
        MessageRequest req = objectMapper.readValue(message.getPayload(), MessageRequest.class);
        if(req.getType().equals("message")){
            //进行消息转发
            transferMessage(user, req);
        }else {
            System.out.println("[WebSocketController] req.type有误!"+message.getPayload());
        }

    }
    //通过这个方法来完成实际的转发工作
    private void transferMessage(User fromUser,MessageRequest req) throws IOException {
        //1.构造响应
        MessageResponse resp = new MessageResponse();
        resp.setType("message");
        resp.setFromId(fromUser.getUserId());
        resp.setFromName(fromUser.getUsername());
        resp.setSessionId(req.getSessionId());
        resp.setContent(req.getContent());
        //把响应对象转化成json格式的字符串
        String respJson = objectMapper.writeValueAsString(resp);
        System.out.println("[transferMessage] respJson: "+respJson);
        //2.根据请求中的sessionId，获取到messageSession里有哪些用户，查询数据库
        List <Friend> friends = messageSessionMapper.getFriendsBySessionId(req.getSessionId(), fromUser.getUserId());
        Friend myself = new Friend();//把当前用户也添加到上述列表中，给自己也发一份此消息
        myself.setFriendId(fromUser.getUserId());
        myself.setFriendName(fromUser.getUsername());
        friends.add(myself);
        //3.给列表中的每一个用户都发一份响应（可支持群聊）
        for (Friend friend:friends) {
            //知道每个用户的userId,进一步的查询刚才准备好的onlineUserMapper,即知道对应的webSocketSession
            WebSocketSession webSocketSession = onlineUserManager.getSession(friend.getFriendId());
            if(webSocketSession == null){
                //如果用户为在线，则不发送
                continue;
            }
            webSocketSession.sendMessage(new TextMessage(respJson));
        }
        //4.转发的消息还需要放到数据库中，
        //需要往message表中写入一条数据
        Message message = new Message();
        message.setFromId(fromUser.getUserId());
        message.setSessionId(req.getSessionId());
        message.setContent(req.getContent());
        //像自增主键，时间，这些属性都可以让sql在数据库里生成
        messageMapper.add(message);

    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        System.out.println("[WebSocketController]连接异常"+exception.toString());
        User user=(User) session.getAttributes().get("user");
        if(user == null){
            return;
        }
        onlineUserManager.offline(user.getUserId(), session);
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        System.out.println("[WebSocketController]连接关闭!"+status.toString());
        User user=(User) session.getAttributes().get("user");
        if(user == null){
            return;
        }
        onlineUserManager.offline(user.getUserId(), session);
    }
}
